iT邦幫忙

2021 iThome 鐵人賽

DAY 8
0

09-08-2021

本章內容
  • THE STATE HOOK
    • Hook 可以做的事情
    • 規則
      • 使用useState()改變背景顏色
  • 初始化狀態(Initialize State)
    • 三種影響conponent 的方式
  • 在JSX外設置狀態
  • 使用之前的狀態設置

THE STATE HOOK

Hook 可以做的事情:

  1. 在components 可以多次使用
  2. 簡化複雜的邏輯,重新組織重點
  3. 避免混淆 this 的行爲
  4. 避免 class constructors 、 binding methods,或更高級的js 行為

規則:

  1. 只從React functions去調用
  2. 只在頂層調用 Hooks,以確保每次渲染組件時以相同的順序調用 Hooks。
  3. 要避免的常見錯誤是在循環、條件或嵌套函數內調用 Hook。
// Instead of confusing React with code like this:
if (userName !== '') {
 useEffect(() => {
   localStorage.setItem('savedUserName', userName);
 });
}
 
// We can accomplish the same goal, while consistently calling our Hook every time:
useEffect(() => {
 if (userName !== '') {
   localStorage.setItem('savedUserName', userName);
 }
});

使用useState()改變背景顏色

const [color, setColor] = useState();

當前狀態(current state) - 範例中的color
更新狀態的函數(state setter) - 範例中的setColor

import React, { useState } from 'react';

export default function ColorPicker() {
  const [color, setColor] = useState();

 const divStyle = {backgroundColor: color};

  return (
    <div style={divStyle}>
      <p>The color is {color}</p>
      <button onClick={() => setColor('Aquamarine')}>
        Aquamarine
      </button>
      <button onClick={() => setColor('BlueViolet')}>
        BlueViolet
      </button>
      <button onClick={() => setColor('Chartreuse')}>
        Chartreuse
      </button>
      <button onClick={() => setColor('CornflowerBlue')}>
        CornflowerBlue
      </button>
    </div>
  );
}

import React, { useState } from 'react';

export default function ColorPicker() {
  const [color, setColor] = useState();
  1. import 使用方法從React函式庫中去調用 {useState} 的方法
  2. 使用方式要放在 function 中
  3. 定義useState()的方法
const [color, setColor] = useState();

初始化狀態(Initialize State)

三種影響conponent 的方式

  1. 第一次渲染期間,使用初始狀態參數。
  2. 當 state setter 被調用時,React 會忽略初始狀態參數並使用新值。
  3. 當組件由於任何其他原因重新渲染時,React 會繼續使用與之前渲染相同的值。
import React, { useState } from 'react';

const colorNames = ['Aquamarine', 'BlueViolet', 'Chartreuse', 'CornflowerBlue', 'Thistle', 'SpringGreen', 'SaddleBrown', 'PapayaWhip', 'MistyRose'];

export default function ColorPicker() {
  const [color, setColor] = useState("Tomato");

 const divStyle = {backgroundColor: color};

  return (
    <div style={divStyle}>
      <p>Selected color: {color}</p>
      {colorNames.map((colorName)=>(
        <button 
          onClick={() => setColor(colorName)} 
          key={colorName}>
       	     {colorName}
      	</button>
      ))}
    </div>
  );
}


map使用方法

在初次頁面使用 "Tomato" 作為初始化的頁面顏色

export default function ColorPicker() {
  const [color, setColor] = useState("Tomato");

 const divStyle = {backgroundColor: color};

在JSX外設置狀態

常見的模式

const handleChange = (event) => {
  const newEmail = event.target.value;
  setEmail(newEmail);
}

也可以這樣簡化

const handleChange = (event) => setEmail(event.target.value);

或是使用解構的方式

const handleChange = ({target}) => setEmail(target.value);

範例:

import React, { useState } from "react";

// regex to match numbers between 1 and 10 digits long
const validPhoneNumber = /^\d{1,10}$/;

export default function PhoneNumber() {
  const [phone, setPhone] = useState('');
  
   const handleChange = ({ target })=> {
     const newPhone = target.value;
     const isValid = validPhoneNumber.test(newPhone);
     if (isValid) {
       setPhone(newPhone);
     }
     // just ignore the event, when new value is invalid
    };

  return (
    <div className='phone'>
      <label for='phone-input'>Phone: </label>
      <input value={phone} onChange={handleChange} id='phone-input' />
    </div>
  );
}

在value 有更動的時候會去執行onChang{handleChange}

<input value={phone} onChange={handleChange} id='phone-input' />
    </div>

使用之前的狀態設置

import React, { useState } from 'react';

export default function QuizNavBar({ questions }) {
  const [questionIndex, setQuestionIndex] = useState(0);

  const goBack = () =>
    setQuestionIndex((prevQuestionIndex) => prevQuestionIndex - 1);
    
  const goToNext = () =>
    setQuestionIndex((prevQuestionIndex) => prevQuestionIndex + 1);

  const onFirstQuestion = questionIndex === 0;
  // 起始值是0
  const onLastQuestion = questionIndex === questions.length - 1;
  // 回到上一個問題,等於問題-1

  return (
    <nav>
      <span>Question #{questionIndex + 1}</span>
      <div>
        <button onClick={goBack} disabled={onFirstQuestion}>
        // 點擊上一步,或是在等於0的時候無法使用
          Go Back
        </button>
        <button onClick={goToNext} disabled={onLastQuestion}>
        // 點擊往下一步,或是在最後一個無法使用
          Next Question
        </button>
      </div>
    </nav>
  );
}


上一篇
< 關於 React: 開始打地基| props、state >
下一篇
< 關於 React: 開始打地基| useEffect() >
系列文
<法式Terrine : React next.js Chakra-UI styled-component 精緻的搭配>18
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言